

import { isArray, isMap, isNumber, isNumberStr, isSet } from '../is'
// import { EventEmitter } from '../event'
// import { addThing, getNewItemId } from '../id'

// const emitter = new EventEmitter();
// const thingName = 'create-proxy';
// addThing(thingName);

declare type printType = 'log' | 'json'
declare type ArrayProxy<T> = Array<T> & {
    drop: (index: number) => void,
    print: (type?: printType) => any,
}

/**
 * 为 Array 创建代理
 * - 可以进行负数索引
 * - 删除指定索引处的元素不留下空位
 * @param target 被代理的目标对象
 * @returns 代理后的对象
 */
function createArrayProxy<T>(target: Array<T>): ArrayProxy<T> {
// function createArrayProxy<T>(target: Array<T>, sideEffects:((...params:any[])=>any)[]=[], ...params:any[]): ArrayProxy<T> {
    // const eventName:string  = getNewItemId(thingName) as string;
    // function subscribeAll() {
    //     // 如有副作用则订阅副作用
    //     if(sideEffects){
    //         for (let index = 0; index < sideEffects.length; index++) {
    //             const sideEffect = sideEffects[index];
    //             emitter.addListener(eventName, sideEffect)
                
    //         }
    //     }
    // }
    
    return new Proxy(target, {  
        get(target: Array<T>, key: string | symbol, receiver) {
            // 劫持 'length'，以实现对 Array.prototype.length 属性的代理
            if (key === 'length') {
                return Reflect.get(target, key, target)
            }
            // 劫持 'push'，以实现对 Array.prototype.push 方法的代理
            else if (key === 'push') {
                /**
                 * 向数组末尾追加新元素，并返回数组的新长度。
                 * @param items 要添加到数组的新元素。
                 */
                return function (...items: T[]): number {
                    let result = Reflect.apply(target.push, target, items)
                    return result
                }
            }
            // 劫持 'pop'，以实现对 Array.prototype.pop 方法的代理
            else if (key === 'pop') {
                /**
                 * 从数组中移除最后一个元素并返回它。
                 * 如果数组为空，则返回undefined，并且不修改数组。
                 */
                return function (): T | undefined {
                    return Reflect.apply(target.pop, target, [])
                }
            }
            // 劫持 'shift'，以实现对 Array.prototype.shift 方法的代理
            else if (key === 'shift') {
                /**
                 * 从数组中移除第一个元素并返回它。
                 * 如果数组为空，则返回undefined，并且不修改数组。
                 */
                return function (): T | undefined {
                    return Reflect.apply(target.shift, target, [])
                }
            }
            // 劫持 'unshift'，以实现对 Array.prototype.unshift 方法的代理
            else if (key === 'unshift') {
                /**
                 * 在数组的开头插入新元素，并返回数组的新长度。
                 * @param items 要在数组开头插入的元素。
                 */
                return function (...items: T[]): number {
                    let result = Reflect.apply(target.unshift, target, items)
                    return result
                }
            }
            // 劫持 'splice'，以实现对 Array.prototype.splice 方法的代理
            else if (key === 'splice') {
                /**
                 * 从数组中移除元素，如有必要，在它们的位置插入新元素，返回已删除的元素。
                 * @param start 数组中从零开始移除元素的位置。
                 * @param deleteCount 要移除的元素数量。
                 * @returns 包含已删除元素的数组。
                 */
                return function (start: number, deleteCount?: number): T[] {
                    return Reflect.apply(target.splice, target, [start, deleteCount])
                }
            }
            // 劫持 'slice'，以实现对 Array.prototype.slice 方法的代理
            else if (key === 'slice') {
                /**
                 * 返回数组的一部分的副本。
                 * 对于start和end，可以使用负索引来指示从数组末尾的偏移量。
                 * 例如，-2表示数组的倒数第二个元素。
                 * @param start 数组指定部分的开始索引。
                 * 如果start未定义，则切片从索引0开始。
                 * @param end 数组指定部分的结束索引。这不包括索引“end”处的元素。
                 * 如果end未定义，则切片扩展到数组的末尾。
                 */
                return function (start?: number, end?: number): T[] {
                    return Reflect.apply(target.slice, target, [start, end])
                }
            }
            // 劫持 'concat'，以实现对 Array.prototype.concat 方法的代理
            else if (key === 'concat') {
                /**
                 * 组合两个或多个数组。
                 * 此方法返回一个新数组，而不修改任何现有数组。
                 * @param items 要添加到数组末尾的其他数组和/或项目。
                 */
                return function (...items: ConcatArray<T>[]): T[] {
                    return Reflect.apply(target.concat, target, items)
                }
            }
            // 劫持 'reverse'，以实现对 Array.prototype.reverse 方法的代理
            else if (key === 'reverse') {
                /**
                 * 就地反转数组中的元素。
                 * 此方法使数组变异，并返回对同一数组的引用。
                 */
                return function (): T[] {
                    return Reflect.apply(target.reverse, target, [])
                }
            }
            // 劫持 'sort'，以实现对 Array.prototype.sort 方法的代理
            else if (key === 'sort') {
                /**
                 * 就地排序数组。
                 * 此方法使数组变异，并返回对同一数组的引用。
                 * @param compareFn 用于确定元素顺序的函数。
                 * 如果第一个参数小于第二个参数，它将返回一个负值，
                 * 如果两个参数相等，则返回零，否则返回正值。
                 * 如果省略，元素将按ASCII字符升序排序。
                 * ```ts
                 * [11,2,22,1].sort((a, b) => a - b)
                 * ```
                 */
                return function (compareFn?: (a: T, b: T) => number) {
                    return Reflect.apply(target.sort, target, [compareFn])
                }
            }
            // 劫持 'forEach'，以实现对 Array.prototype.forEach 方法的代理
            else if (key === 'forEach') {
                /**
                 * 对数组中的每个元素执行指定的操作。
                 * @param callbackfn  最多接受三个参数的函数。forEach为数组中的每个元素调用一次callbackfn函数。
                 * @param thisArg  this关键字可以在callbackfn函数中引用的对象。如果省略thisArg，则使用undefined作为this值。
                 */
                return function (callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void {
                    return Reflect.apply(target.forEach, target, [callbackfn, thisArg])
                }
            }
            // 劫持 'map'，以实现对 Array.prototype.map 方法的代理
            else if (key === 'map') {
                /**
                 * 对数组的每个元素调用定义的回调函数，并返回包含结果的数组。
                 * @param callbackfn 最多接受三个参数的函数。map方法为数组中的每个元素调用一次callbackfn函数。
                 * @param thisArg this关键字可以在callbackfn函数中引用的对象。如果省略thisArg，则使用undefined作为this值。
                 */
                return function <U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[] {
                    return Reflect.apply(target.map, target, [callbackfn, thisArg]) as U[];
                }
            }
            // 劫持 'filter'，以实现对 Array.prototype.filter 方法的代理
            else if (key === 'filter') {
                /**
                 * 返回满足回调函数中指定条件的数组元素。
                 * @param predicate 最多接受三个参数的函数。filter方法为数组中的每个元素调用一次谓词函数。
                 * @param thisArg this 关键字可以在谓词函数中引用的对象。如果省略thisArg，则使用undefined作为this值。
                 */
                return function <S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[] {
                    return Reflect.apply(target.filter, target, [predicate, thisArg]) as S[];
                }
            }
            // 劫持 'reduce'，以实现对 Array.prototype.reduce 方法的代理
            else if (key === 'reduce') {
                /**
                 * 为数组中的所有元素调用指定的回调函数。回调函数的返回值是累加的结果，并在下次调用回调函数时作为参数提供。
                 * @param callbackfn 为数组中的所有元素调用指定的回调函数。回调函数的返回值是累加的结果，并在下次调用回调函数时作为参数提供。
                 * @param initialValue 如果指定了initialValue，它将用作开始累加的初始值。对callbackfn函数的第一次调用将此值作为参数而不是数组值提供。
                 */
                return function (callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T) {
                    return Reflect.apply(target.reduce, target, [callbackfn, initialValue])
                }
            }
            // 劫持 'reduceRight'，以实现对 Array.prototype.reduceRight 方法的代理
            else if (key === 'reduceRight') {
                /**
                 * 按降序为数组中的所有元素调用指定的回调函数。回调函数的返回值是累加的结果，并在下次调用回调函数时作为参数提供。
                 * @param callbackfn 最多接受四个参数的函数。reduceRight方法为数组中的每个元素调用一次callbackfn函数。
                 * @param initialValue 如果指定了initialValue，它将用作开始累加的初始值。对callbackfn函数的第一次调用将此值作为参数而不是数组值提供。
                 */
                return function <U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue?: U): U {
                    return Reflect.apply(target.reduceRight, target, [callbackfn, initialValue]) as U
                }
            }
            // 劫持 'every'，以实现对 Array.prototype.every 方法的代理
            else if (key === 'every') {
                /**
                 *确定数组的所有成员是否满足指定的测试。
                 * @param predicate 最多接受三个参数的函数。
                 * every方法为数组中的每个元素调用谓词函数，
                 * 直到谓词返回一个可强制为布尔值false的值，或者直到数组结束。
                 * @param thisArg this关键字可以在谓词函数中引用的对象。
                 * 如果省略thisArg，则使用undefined作为this值。
                 */
                return function <S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): boolean {
                    return Reflect.apply(target.every, target, [predicate, thisArg])
                }
            }
            // 劫持 'indexOf'，以实现对 Array.prototype.indexOf 方法的代理
            else if (key === 'indexOf') {
                /**
                 * 返回数组中某个值第一次出现的索引，如果不存在，则返回-1。
                 * @param searchElement 要在数组中定位的值。
                 * @param fromIndex 开始搜索的数组索引。如果省略fromIndex，则从索引0开始搜索。
                 */
                return function (searchElement: T, fromIndex?: number): number {
                    return Reflect.apply(target.indexOf, target, [searchElement, fromIndex])
                }
            }
            // 劫持 'lastIndexOf'，以实现对 Array.prototype.lastIndexOf 方法的代理
            else if (key === 'lastIndexOf') {
                /**
                 * 返回指定值在数组中最后一次出现的索引，如果不存在，则返回-1。
                 * @param searchElement 要在数组中定位的值。
                 * @param fromIndex 开始向后搜索的数组索引。如果省略fromIndex，则从数组中的最后一个索引开始搜索。
                 */
                return function (searchElement: T, fromIndex?: number): number {
                    return Reflect.apply(target.lastIndexOf, target, [searchElement, fromIndex])
                }
            }
            // 劫持 'entries'，以实现对 Array.prototype.entries 方法的代理
            else if (key === 'entries') {
                /**为数组中的每个条目返回一个可迭代的键/值对 */
                return function (): IterableIterator<[number, T]> {
                    return Reflect.apply(target.entries, target, [])
                }
            }
            // 劫持 'keys'，以实现对 Array.prototype.keys 方法的代理
            else if (key === 'keys') {
                /**返回数组中的可重复键 */
                return function (): IterableIterator<number> {
                    return Reflect.apply(target.keys, target, [])
                }
            }
            // 劫持 'values'，以实现对 Array.prototype.values 方法的代理
            else if (key === 'values') {
                /**返回数组中可迭代的值 */
                return function (): IterableIterator<T> {
                    return Reflect.apply(target.values, target, [])
                }
            }
            // 迭代器
            else if (key === Symbol.iterator) {
                /** Iterator */
                return function (): IterableIterator<T> {
                    return Reflect.apply(target[Symbol.iterator], target, [])
                }
            }
            // 劫持 'find'，以实现对 Array.prototype.find 方法的代理
            else if (key === 'find') {
                /**
                 * 返回数组中第一个元素的值，其中谓词为真，否则为未定义。
                 * @param predicate find按升序对数组的每个元素调用一次谓词，直到找到一个谓词返回true的元素。如果找到这样的元素，find会立即返回该元素的值。否则，find返回undefined。
                 * @param thisArg 如果提供的话，它将被用作每次谓词调用的this值。如果没有提供，则使用undefined。
                 */
                return function <S extends T>(predicate: (value: T, index: number, obj: T[]) => value is S, thisArg?: any): S | undefined {
                    return Reflect.apply(target.find, target, [predicate, thisArg]) as any;
                }
            }
            // 劫持 'findIndex'，以实现对 Array.prototype.findIndex 方法的代理
            else if (key === 'findIndex') {
                /**
                 * 调用函数，将指定的对象作为此值，将指定数组的元素作为参数。
                 * @param target 要调用的函数。
                 * @param thisArgument 要用作此对象的对象。
                 * @param argumentsList 要传递给函数的参数值数组。
                 */
                return function (predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): number {
                    return Reflect.apply(target.findIndex, target, [predicate, thisArg])
                }
            }
            // 劫持 'fill'，以实现对 Array.prototype.fill 方法的代理
            else if (key === 'fill') {
                /**
                 * 将从 “start” 到 “end” 索引的所有数组元素更改为静态 “value”,并返回修改后的数组
                 * @param value 用于填充数组部分的值
                 * @param start 开始填充数组的索引。如果 start 为负，则被视为 length+start，其中length是数组的长度。
                 * @param end 停止填充数组的索引。如果 end 为负，则被视为 length+end。
                 */
                return function (value: T, start?: number, end?: number) {
                    return Reflect.apply(target.fill, target, [value, start, end])
                }
            }
            // 劫持 'includes'，以实现对 Array.prototype.includes 方法的代理
            else if (key === 'includes') {
                /**
                 * 确定数组是否包含某个元素，根据情况返回true或false。
                 * @param searchElement 要搜索的元素。
                 * @param fromIndex 此数组中开始搜索searchElement的位置。
                 */
                return function (searchElement: T, fromIndex?: number): boolean {
                    return Reflect.apply(target.includes, target, [searchElement, fromIndex])
                }
            }
            // 劫持 'some'，以实现对 Array.prototype.some 方法的代理
            else if (key === 'some') {
                /**
                 * 确定指定的回调函数是否为数组中的任何元素返回true。
                 * @param predicate 最多接受三个参数的函数。
                 * some方法为数组中的每个元素调用谓词函数，直到谓词返回一个可强制为布尔值true的值，或者直到数组结束。
                 * @param thisArg this关键字可以在谓词函数中引用的对象。
                 * 如果省略thisArg，则使用undefined作为this值。
                 */
                return function (predicate: (value: T, index: number, array: T[]) => unknown, thisArg?: any): boolean {
                    return Reflect.apply(target.some, target, [predicate, thisArg])
                }
            }
            // 劫持 'copyWithin'，以实现对 Array.prototype.copyWithin 方法的代理
            else if (key === 'copyWithin') {
                /**
                 * 在将由start和end标识的数组的一部分复制到从position target开始的同一数组后，返回此对象
                 * @param _target 如果target为负，则被视为length+target，其中length是数组的长度。
                 * @param start 如果start为负，则被视为length+start。如果end为负，则被视为length+end。
                 * @param end 如果未指定，此对象的长度将用作其默认值。
                 */
                return function (_target: number, start: number, end?: number) {
                    return Reflect.apply(target.copyWithin, key, [_target, start, end])
                }
            }
            else if (key === 'drop') {
                /**
                 * 扩展用于删除指定索引处元素的 dorp 方法
                 */
                return function (index: number) {
                    // 删除正数索引指定的元素
                    if (index > 0) {
                        Reflect.deleteProperty(target, index);
                        for (let i = index; i < target.length - 1; i++) {
                            target[i] = target[i + 1];
                        }
                        Reflect.apply(target.pop, target, [])
                    }
                    // 删除负数索引指定的元素
                    else {
                        const _index = index + target.length;
                        Reflect.deleteProperty(target, _index);
                        for (let i = _index; i < target.length - 1; i++) {
                            target[i] = target[i + 1];
                        }
                        Reflect.apply(target.pop, target, [])
                    }
                }
            }
            else if (key === 'print') {
                return function (type: printType = 'log') {
                    if (type === "json") {
                        console.log(JSON.stringify(target, null, 2));
                    } else {
                        console.log(target);
                    }
                }
            }
            // 数字用于索引数组
            else if (isNumber(key) || isNumberStr(key)) {
                let _key: number;
                if (isNumberStr(key)) {
                    _key = parseInt(key as string);
                } else {
                    _key = key as unknown as number
                }

                // 正数和0的索引
                if (_key >= 0) {
                    return Reflect.get(target, _key, receiver)
                }
                // 负数索引，则转换为对应的正数索引
                else {
                    const index = target.length + _key;
                    return Reflect.get(target, index, receiver)
                }
            }
            // 其他情况，直接返回原对象的属性或方法
            else {
                // console.log('elseelseelseelseelseelse');
                // console.log(typeof key);
                return Reflect.get(target, key, receiver)
            }
        },
        // 实现负数索引
        set(target: Array<T>, key: any, value: T) {
            // 针对于数组，认定为数组索引
            if (isNumber(key)) {
                // 正数和 0
                if (key >= 0) {
                    Reflect.set(target, key, value);
                } 
                // 负数
                else {
                    const index = target.length + key;
                    Reflect.set(target, index, value);
                }
                return true;
            }
            return false
        },
        // 实现 delete 不留下空位
        deleteProperty(target: T[], key: string | symbol | number) {
            if (isNumber(key) || isNumberStr(key)) {
                let _key: number;
                if (isNumberStr(key)) {
                    _key = parseInt(key as string);
                } else {
                    _key = key as unknown as number
                }
                // 正数索引下的删除元素
                if (_key >= 0) {
                    Reflect.deleteProperty(target, _key);
                    for (let i = _key; i < target.length - 1; i++) {
                        target[i] = target[i + 1];
                    }
                    Reflect.apply(target.pop, target, [])

                }
                // 负数索引下的删除元素
                else {
                    const index = target.length + _key;
                    Reflect.deleteProperty(target, index);
                    for (let i = index; i < target.length - 1; i++) {
                        target[i] = target[i + 1];
                    }
                    Reflect.apply(target.pop, target, [])
                }
                return true
            }
            return false
        },
        // 对原有的 in 特性进行增强
        has(target: T[], key: any) {
            // JavaScript 的 in 会强制转换类型
            // 这里已经拿不到 key 的真实类型，因此拦截是无意义的
            // if(Reflect.has(target,key)){
            //     console.log('--------key =',key);
            //     let counter = 0;
            //     target.forEach((item:any)=>{
            //         console.log('--------item =',item);
            //         if(item===key){
            //             counter++;
            //         }
            //     })
            //     return counter > 0
            // }
            // return false;
            return Reflect.has(target, key)
        }
    }) as ArrayProxy<T>
}

/**
 * 为 Set 创建代理
 * @param target 
 * @returns 被代理的对象
 */
function createSetProxy<T extends Set<T>>(target: T) {
    return new Proxy(target, {
        get(target: Set<T>, key: string | symbol, receiver) {
            // 劫持 'size'，以实现对 Set.prototype.size 属性的代理
            if (key === 'size') {
                return Reflect.get(target, key, target)
            }
            // 劫持 'add'，以实现对 Set.prototype.add 方法的代理
            else if (key === 'add') {
                return function (this: Set<T>, ...args: T[]) {
                    return Reflect.apply(target.add, target, args)
                }
            }
            // 劫持 'clear'，以实现对 Set.prototype.clear 方法的代理
            else if (key === 'clear') {
                return function () {
                    return Reflect.apply(target.clear, target, [])
                }
            }
            // 劫持 'delete'，以实现对 Set.prototype.delete 方法的代理
            else if (key === 'delete') {
                return function (this: Set<T>, ...args: T[]) {
                    return Reflect.apply(target.delete, target, args)
                }
            }
            // 劫持 'entries'，以实现对 Set.prototype.entries 方法的代理
            else if (key === 'entries') {
                return function (this: Set<T>) {
                    return Reflect.apply(target.entries, target, [])
                }
            }
            // 劫持 'forEach'，以实现对 Set.prototype.forEach 方法的代理
            else if (key === 'forEach') {
                return function (this: Set<T>, callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any) {
                    return Reflect.apply(target.forEach, target, [callbackfn, thisArg])
                }
            }
            // 劫持 'has'，以实现对 Set.prototype.has 方法的代理
            else if (key === 'has') {
                return function (this: Set<T>, ...args: T[]) {
                    return Reflect.apply(target.has, target, args)
                }
            }
            // 劫持 'keys'，以实现对 Set.prototype.keys 方法的代理
            else if (key === 'keys') {
                return function (this: Set<T>) {
                    return Reflect.apply(target.keys, target, [])
                }
            }
            // 劫持 'values'，以实现对 Set.prototype.values 方法的代理
            else if (key === 'values') {
                return function (this: Set<T>) {
                    return Reflect.apply(target.values, target, [])
                }
            }
            // 劫持 'Symbol.iterator'，以实现对 Set.prototype[Symbol.iterator] 方法的代理
            else if (key === Symbol.iterator) {
                return function (this: Set<T>) {
                    return Reflect.apply(target[Symbol.iterator], target, [])
                }
            }
            // 其他情况，直接返回原对象的属性或方法
            else {
                return Reflect.get(target, key, receiver)
            }
        }
    })
}


/**
 * 为 Map 创建代理
 * @param target 
 * @returns 被代理的对象
 */
function createMapProxy<K, V>(target: Map<K, V>) {
    return new Proxy(target, {
        get(target: Map<K, V>, key: string | symbol, receiver) {
            // 劫持 'size'，以实现对 Map.prototype.size 属性的代理
            if (key === 'size') {
                return Reflect.get(target, key, target)
            }
            // 劫持 'clear'，以实现对 Map.prototype.clear 方法的代理
            else if (key === 'clear') {
                /**
                 * @returns 如果 Map 中的元素存在并已被删除，则为true如果元素不存在，则为false。
                 */
                return function () {
                    return Reflect.apply(target.clear, target, [])
                }
            }
            // 劫持 'delete'，以实现对 Map.prototype.delete 方法的代理
            else if (key === 'delete') {
                /**
                 * @returns 如果 Map 中的元素存在并已被删除，则为true如果元素不存在，则为false。
                 */
                return function (key: K): boolean {
                    return Reflect.apply(target.delete, target, [key])
                }
            }
            // 劫持 'forEach'，以实现对 Map.prototype.forEach 方法的代理
            else if (key === 'forEach') {
                /** 按照插入顺序，对映射中的每个键/值对执行一次提供的函数。 */
                return function (callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void {
                    return Reflect.apply(target.forEach, target, [callbackfn, thisArg])
                }
            }
            // 劫持 'get'，以实现对 Map.prototype.get 方法的代理
            else if (key === 'get') {
                /**
                 * 从Map对象中返回指定的元素。如果与所提供的键相关联的值是一个对象，那么您将获得对该对象的引用，对该对象所做的任何更改都将有效地在映射中修改它。
                 * @returns 返回与指定键关联的元素。如果没有元素与指定的键相关联，则返回undefined。
                 */
                return function (key: K): V | undefined {
                    return Reflect.apply(target.get, target, [key])
                }
            }
            // 劫持 'has'，以实现对 Map.prototype.has 方法的代理
            else if (key === 'has') {
                /**
                 * @returns 布尔值，指示具有指定键的元素是否存在。
                 */
                return function (key: K): boolean {
                    return Reflect.apply(target.has, target, [key])
                }
            }
            // 劫持 'set'，以实现对 Map.prototype.set 方法的代理
            else if (key === 'set') {
                /**Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated. */
                return function (key: K, value: V) {
                    return Reflect.apply(target.set, target, [key, value])
                }
            }
            // 劫持 'keys'，以实现对 Map.prototype.keys 方法的代理
            else if (key === 'keys') {
                /**Returns an iterable of keys in the map */
                return function (): IterableIterator<K> {
                    return Reflect.apply(target.keys, target, [])
                }
            }
            // 劫持 'values'，以实现对 Map.prototype.values 方法的代理
            else if (key === 'values') {
                /**Returns an iterable of values in the map */
                return function (): IterableIterator<V> {
                    return Reflect.apply(target.values, target, [])
                }
            }
            // 劫持 'entries'，以实现对 Map.prototype.entries 方法的代理
            else if (key === 'entries') {
                /**Returns an iterable of key, value pairs for every entry in the map. */
                return function (): IterableIterator<[K, V]> {
                    return Reflect.apply(target.entries, target, [])
                }
            }
            // 劫持 'Symbol.iterator'，以实现对 Map.prototype[Symbol.iterator] 方法的代理
            else if (key === Symbol.iterator) {
                /**Returns an iterable of entries in the map. */
                return function (): IterableIterator<[K, V]> {
                    return Reflect.apply(target[Symbol.iterator], target, [])
                }
            }
            // 其他情况，直接返回原对象的属性或方法
            else {
                return Reflect.get(target, key, receiver)
            }
        }
    })
}

/**
 * 为 Array、Set、Map 创建代理
 * 
 * @param {Set|Map} target 要创建代理的目标对象
 * @param {Function} callback 回调函数，用于监听数据变化
 * 
 * @returns {Set|Map} 返回代理对象
 */
function createProxy(target: unknown) {
    // 代理 Array
    if (isArray(target)) {
        return createArrayProxy(target)
    }
    // 代理 ES6 Set
    else if (isSet(target)) {
        return createSetProxy(target)
    }
    // 代理 ES6 Map
    else if (isMap(target)) {
        return createMapProxy(target)
    }
}

export {
    createArrayProxy,
    createSetProxy,
    createMapProxy,
    createProxy
}